import packages

library(ggplot2)
library(grid)
library(dplyr)
library(tidyr)
library(htmlwidgets)
library(plotly)
library(purrr)
library(stringr)
library(DT)

import data

scf <- read.table("survey_SCF.txt", sep = ",", header = TRUE) 

1. Debt over time

Debt and debt ratio over time

data set

scf_debt <- scf %>%
  select(CASEID,YEAR,DEBT,ASSET,EDN_INST, LEVRATIO, DEBT2INC) %>%
  group_by(YEAR) %>% 
  summarise(debt_income = mean(DEBT2INC),
            debt_asset= mean(LEVRATIO),
            average_debt = mean(DEBT)) %>%
  mutate(average_debt = average_debt/1000)#make it by 1000 dollars

chart1

ggplot(scf_debt)+
  geom_bar(aes(x=YEAR, y= average_debt, fill="average debt"),
             stat="identity", width = 1)+
  geom_line(aes(x=YEAR, y=debt_asset*200,
              color = "debt/asset"),
              group = 1, size = 1.2)+
  geom_text(aes(label=round(debt_asset,2), 
                x=YEAR,y=debt_asset*200),
              colour="grey10", size = 3, vjust = 2)+
  geom_text(aes(label=round(average_debt), 
                x=YEAR, y=average_debt), 
              colour="grey10", size = 3, vjust = -1)+
  scale_x_continuous(name = "Survey Year",
                       limits = c(1986, 2019),
                       breaks = seq(1989, 2016, by = 3),
                       expand = c(0, 0)) +
  scale_y_continuous(name = "Average Debt \nby 1,000 dollars",
                     limits = c(0,400),
                     sec.axis = sec_axis(~./200, name = "debt/asset \n[%]")) +
  scale_colour_manual(" ", values=c("debt/asset" = "#CC6600"))+ 
  #add a second y-axis for the ratio
  scale_fill_manual("",values="#FFCC66")+
  theme_minimal()+
  theme(legend.title = element_blank(),
        legend.text = element_text(size = 10, color = "gray10"),
        legend.position = "top",
        plot.title = element_text(face = "bold", color = "black", size = 20))+
  ggtitle("1.Debt over time")

In chart1, the line chart shows the trend of average debt/asset ratio from 1989 to 2016 and the bar chart shows the trend of average debt from 1989 to 2016.
Although the average amount of debt fluctuated, it did not make a great increase over the years. However, the debt-to-asset ratio increased in a great scale over time and even got over 1 after 2010.
The combination of line and bar chart can show the amount of debt and the trend of ratio over year at the same time therefore this chart is proper for the research.

The proportion of Student loan

dataset

scf_loan <- scf %>%
  select(CASEID, YEAR, DEBT, EDN_INST, NH_MORT, OTHLOC, CCBAL, INSTALL, VEH_INST) %>%
  group_by(YEAR) %>%
  summarise(education = round(mean(EDN_INST),2),
            mortgage = round(mean(NH_MORT),2),
            other = round(mean(OTHLOC),2),
            `credit card` = round(mean(CCBAL),2),
            installment = round(mean(INSTALL),2),
            vehicle = round(mean(VEH_INST),2))%>%
  gather(key = "loan", value = "amount", education, mortgage,other,`credit card`,installment,vehicle) %>%
  split(.$YEAR)%>%
  map(~mutate(.,prop = round(.$amount/sum(.$amount),2)))%>% 
  #calculate the proportion by year
  bind_rows()

scf_loan$loan <- factor(scf_loan$loan,
                      levels = c("mortgage","installment",
                                 "vehicle","credit card",
                                 "other","education")) 
#education should be the last level in order to make the changes of proportion clear

chart2

loan <- ggplot(scf_loan)+
  geom_col(aes(x = YEAR, y = amount, fill = loan),position = "fill", width = 1)+
  scale_x_continuous(name = "Survey Year",
                       limits = c(1986, 2019),
                       breaks = seq(1989, 2016, by = 3),
                       expand = c(0, 0)) +
  scale_y_continuous(name = "proportion")+
  coord_flip()+
  scale_fill_manual(values = c("#FFCC66","#FF9900","#CC6600","#CC6633","#993300","#330000")) +
  theme_minimal()+
  guides(fill = guide_legend(nrow = 1)) +
  theme(legend.title = element_blank(),
        legend.justification = 0.05,
        legend.position = "top",
        legend.text = element_text(size = 10, color = "gray10"),
        legend.key.height=unit(1,"line"),
        legend.key.width=unit(1,"line"),
        plot.title = element_text(face = "bold", color = "black", size = 20))+
  ggtitle("2.Proportion of Loans")

loan

Chart2 shows the proportion of the average of different loans every survey year.
Comparing with other type of loans, student loan only takes a small proportion in debt (the largest is about 3% in 2016), but it got more important from 1989 to 2016. Mortage loan and installment loan are the top 2 loan among all the loans. Mortage loan takes more than a half proportion of the debt in most of the survey years.

Student Loan over time

dataset

scf_edu <- scf %>%
  select(CASEID,YEAR,DEBT,ASSET,EDN_INST) %>%
  filter(DEBT != 0) %>%
  mutate(edu_ratio = EDN_INST/DEBT) %>%
  group_by(YEAR) %>%
  summarise(average_edu_ratio = mean(edu_ratio),average_edu = mean(EDN_INST))

chart3

ggplot(scf_edu) + 
  geom_bar(aes(x=YEAR, y= average_edu, fill="edu"),
             stat="identity", width = 1)+
  geom_line(aes(x=YEAR, y=average_edu_ratio*100000,
              color = "ratio"),
              group = 1, size = 1.2)+
  geom_text(aes(label=round(average_edu_ratio*100,2), 
                x=YEAR,y=average_edu_ratio*100000),
              colour="grey10", size = 3, vjust = -1)+
  geom_text(aes(label=round(average_edu), 
                x=YEAR, y=average_edu), 
              colour="grey10", size = 3, vjust = -1)+
  scale_x_continuous(name = "Survey Year",
                       limits = c(1986, 2019),
                       breaks = seq(1989, 2016, by = 3),
                       expand = c(0, 0)) +
  scale_y_continuous(name = "Average Education Loan",
                     limits = c(0,15000),
                     sec.axis = sec_axis(~./1000,name = "education loan/debt \n[%]"))+
  scale_colour_manual(" ", values=c("ratio" = "#CC6600"))+
  scale_fill_manual("",values="#FFCC66")+
  theme_minimal()+
  theme(legend.title = element_blank(),
        legend.text = element_text(size = 10, color = "gray10"),
        legend.position = "top",
        plot.title = element_text(face = "bold", color = "black", size = 20))+
  ggtitle("Education Loan over time")

In chart3, the line chart shows the trend of average student_loan/debt ratio from 1989 to 2016 and the bar chart shows the trend of average student loan from 1989 to 2016.
The proportion of the Student Loan in the line graph is calculated by EDN_INST/DEBT. Noted that there are many respondents without any debt, so these respondents are removed from this analysis. The proportions of student loan in this line graph are larger than the proportions in stacked 100% bar chart above because of the different calculation methods. The proportion and the average amount of student loan have been increasing over time.
Regardlessness of the different nunmber in chart2 and chart3, the evidence shows that student loan does become more important over years.

The combination of line and bar chart can show the amount of student loan and the trend of ratio over year at the same time; however, it cannot indicates the other kinds of loans and there proportion in the debt. Chart2 can give the reader a direct feeling of the proportion of each loan and the change of student loan over years. Therefore, I recommand chart2 to show the growing importance of student loan over time.

2.Tell me who you are

Get married and kids, get stable and broke.

This topic is a discussion of the relationship between student loan and the number of kids in different the marital status in 2016. I use two kinds of visualization in this discussion. The first, chart4, is a bubble chart with fit line by the method of loess. The second, chart5, is a dodged bar chart with the fit line.

dataset

scf_2016 <- scf %>%
  filter(YEAR == 2016)%>%
  select(CASEID,YEAR,DEBT,ASSET,EDN_INST, EDCL, AGE, FAMSTRUCT, MARRIED,KIDS,EDUC,HHSEX,RACE)

scf_2016$MARRIED <- factor(scf_2016$MARRIED,
                           levels = c("1","2"),
                           labels = c("Married/Living with partner",
                                      "Neither married nor living with partner"))

scf_marital <- scf_2016 %>%
  group_by(MARRIED, KIDS) %>%
  summarise(edu_loan = mean(EDN_INST), n = n())
#n for the number of respondents in this category
#check the mean and standard deviation of student loan in different marital status
scf_marital %>%
  group_by(MARRIED)%>%
  summarise(mean = mean(edu_loan), sd = sd(edu_loan))

chart4: bubble and fit line

ggplot(scf_marital,aes(x = KIDS))+
  geom_point(aes(y = edu_loan, group = MARRIED, 
                 color = MARRIED, size = n), alpha = 0.8)+
  geom_smooth(aes(y = edu_loan, group = MARRIED, color = MARRIED),
               method = 'loess',se = FALSE)+
  scale_x_continuous(name = "Number of Kids",
                     breaks = seq(0,7, by = 1))+
  scale_y_continuous(name = "Average Student Loan",
                     breaks = seq(0,12500, by = 2500))+
  scale_colour_manual(name = "Marital Status", 
                      values=c("#FFCC66", "#CC6600"))+
  scale_size(name = "Number of Observations",
             range = c(4,12))+
  theme_minimal()+
  theme(legend.text = element_text(size = 10, color = "gray10"),
        legend.position = "right",
        plot.title = element_text(face = "bold", color = "black", size = 20))+
  ggtitle("4.Get married and kids, get stable and broke")

The fit line and the location of the bubble in chart4 show the relationship between the number of kids and the student loan. The color shows the different marital status and the size of the bubble shows the number of respondents in each category which indicates the bias of this analysis.
The stability here does not mean that marriage helps in saving money to make a more stable life. In fact, get married makes a stable and high expense for educational loans no matter how many children the household has. The average education loan in the married respondent is 8378.24 dollars, which is about 2000 dollars higher than the others. Also, we can tell from the lower standard deviation that the higher stability of expenses on educational loans that married people have.
As for the people who are neither married or living with a partner, the average educational loan expenses can hit the top at almost 12000 dollars if they have 3 children; however, it goes down on a large scale when the number of children is over 3.
Additionally, no matter married or not, people without kids usually pay fewer education loans as it shows in the graph.
Noted that the result has a bias because the number of observations is relatively limited the more children the households have.

chart5: bar chart and fit line

ggplot(scf_marital,aes(x = KIDS))+
  geom_bar(aes(y = edu_loan, group = MARRIED, fill = MARRIED),
              size  = 4, width = 0.5, stat = "identity", alpha =0.7,
           position=position_dodge())+
  geom_smooth(aes(y = edu_loan, group = MARRIED, color = MARRIED),
               method = 'loess',se = FALSE)+
  geom_text(aes(label=round(edu_loan), 
                y=edu_loan, group = MARRIED), 
            colour="grey10", size = 3, vjust = -1, 
            position = position_dodge(0.9))+
  scale_x_continuous(name = "Number of Kids",
                     breaks = seq(0,7, by = 1))+
  scale_y_continuous(name = "Average Student Loan",
                     limits = c(0,14000),
                     breaks = seq(0,15000, by = 2500))+
  scale_colour_manual(name = "average edu loan", 
                      values=c("#CC6666","#990033"))+
  scale_fill_manual(name = "average edu loan", 
                      values=c("#FFCC66", "#CC6600"))+
  theme_minimal()+
  theme(legend.title = element_blank(),
        legend.text = element_text(size = 10, color = "gray10"),
        legend.position = "top",
        plot.title = element_text(face = "bold", color = "black", size = 20))+
  ggtitle("5.Get married and kids, get stable and broke")

We can draw the same conclusion as chart4 from chart5 except for the number of respondents in each category. Additionally, the bar chart in chart5 can tell the amount of average student loan more clearly.

For getting more information, I think chart4 is better than chart5 in this topic. Chart4 not only displays the relationship between debt, kids and marriage, but shows the number of people in each category in the survey.

Young, Smart but Poor

This topic discusses the relationship between age and student loan in different education background in 2016 with scatter and fit line (chart6).

dataset

scf_age <- scf_2016 %>%
  group_by(AGE, EDCL)%>%
  summarise(edu_loan = round(mean(EDN_INST),2),n())

scf_age$edu <- factor(scf_age$EDCL,
                       levels = c("1","2","3","4"),
                       labels = c("No high school diploma/GED",
                                  "High school diploma/GED",
                                  "Some college","College degree"))

chart6

age_edu <- ggplot(scf_age, aes(x = AGE,y = edu_loan))+
  geom_point(aes(color = edu),shape = 1,size = 2,stroke = 1.5)+
  geom_smooth(color = "#990000", method = "loess", se = FALSE)+
  scale_x_continuous(name = "Age of Household",
                     breaks = seq(18,96,by=6))+
  scale_y_continuous(name = "Average Student Loan",
                     breaks = seq(0,50000,by = 10000))+
  scale_color_manual(values = c("#FFCC66","#FF9900","#CC6600","#660000"))+
  theme_minimal()+
  theme(legend.title = element_blank(),
        legend.text = element_text(size = 10, color = "gray10"),
        legend.position = "top",
        plot.title = element_text(face = "bold", color = "black", size = 20))+
  ggtitle("6.Young, Smart but Poor")
age_edu 

Each point in the scatter plot shows the average student loan in an certain age and education background. The darker of the point’s color, the higher education the respondent got. The fit line shows the relationship between age and student loan as a whole.
The color in chart6 tells that people with high degree tend to have more student loan. For instance the average student loan of college degree people at age of 28 can be more than 55,000 dollars, while the one with other degrees are all less than 20,000 dollars.
For all kind s of observations, the average student loan goes up with age before about 30, then it decrease as getting older. After about 70, the average amount of student loan get zero no matter the educational background.

The scatter plot with color can give readers a clear information of the education background pattern and the fit line shows the relationship between age and student loan well. Therefore, Chart6 is suitable for this topic.

3.Wealth and Income Distribution

This section discusses the relationship between student loan and both networth and income in 2016 with two simple bar charts (chart7).

dataset

scf_money <- scf %>%
  filter(YEAR == 2016)%>%
  select(CASEID,YEAR,DEBT,ASSET,EDN_INST, INCOME, INCCAT, NETWORTH, NWCAT)

#make networth and income have the same number of categories and convert it into percentile scale.
scf_money$NWCAT <- scf_money$NWCAT*20-10
scf_money$INCCAT[scf_money$INCCAT == 6] <- 5
scf_money$INCCAT <- scf_money$INCCAT*20-10
#networth percentile and student loan
scf_nw <- scf_money %>%
  group_by(NWCAT) %>%
  summarise(networth = median(NETWORTH), edu_loan = mean(EDN_INST))%>%
  mutate(percentile = NWCAT) %>%
  select(percentile,networth,edu_loan)%>%
  gather(key = "key",value = "value",networth)%>%
  select(percentile,key,edu_loan)
#income percentile and student loan
scf_inc <- scf_money %>%
  group_by(INCCAT) %>%
  summarise(income = median(INCOME), edu_loan = mean(EDN_INST))%>%
  mutate(percentile = INCCAT)%>%
  select(percentile,income,edu_loan)%>%
  gather(key = "key",value = "value",income)%>%
  select(percentile,key,edu_loan)
#combine
scf_money2 <- rbind(scf_nw,scf_inc)

chart7

ggplot(scf_money2)+
  geom_bar(aes(x = percentile, y = edu_loan, group = key, fill = key), 
           stat = "identity", width = 10)+
  facet_wrap(~ key)+ #make it into two seperate charts
  geom_text(aes(label=round(edu_loan), x = percentile, y=edu_loan, 
                group = key), colour="grey10", size = 3, vjust = -1)+
  scale_x_continuous(name = "percentile",
                     limits = c(0,100),
                     breaks = seq(0,100,by=20))+
  scale_y_continuous(name = "Average Student Loan",
                     limits = c(0,18000))+
  scale_fill_manual(name = "category", 
                      values=c("#FFCC66", "#CC6600"))+
  theme_minimal()+
  theme(legend.title = element_blank(),
        legend.text = element_text(size = 10, color = "gray10"),
        legend.position = "right",
        plot.title = element_text(face = "bold", color = "black", size = 20))+
  ggtitle("7.Wealth and Income Distribution")

The bar chart on the left in chart7 shows that the average student loan increases then decreases as income going up. People in 40-60 percentile of income have the highest average student loan, 9266 dollars. This maybe because the higher-income class tends to spend more on education but they can pay more or pay off with there own income without the help of debt when the income gets even higher. Poor middle class:(
However, the discussion on networth shows a totally different pattern. Less networth reveals more debt, especially first 20% (average student loan more than 17,000 dollars) as it displays on the right. People from 20% to 80% percentile have an average student loan between 4,000 and 6,000 dollars, while 80% to 100% have the average loan less than 2,000 dollars.

Two seperate bar charts can make reader understand the student loan in different networth and income and compare the patterns of them easily. Therefore, chart7 is recommend for discussing wealth and income distribution.

4.Going broke

Bankruptcy and Student Loan

This part discusses the proportion of bankruptcy with and without student loans over time after 1998 because there is no bankruptcy reported in the original dataset before.

dataset

scf_broke <- scf %>%
  filter(YEAR >= 1998) %>%
  select(YEAR,EDN_INST, BNKRUPLAST5)

#divide into two categories: with and without student loan
scf_broke$LOAN <- ifelse(scf_broke$EDN_INST != 0, "had loan", "no loan")

scf_broke$BNKRUPLAST5 <- factor(scf_broke$BNKRUPLAST5,
                                levels = c("1","0"),
                                labels = c("has",
                                           "no"))
#count the number of each categories
scf_broke <- scf_broke %>%
  group_by(YEAR, BNKRUPLAST5, LOAN)%>%
  summarise(n=n()) %>%
  spread(BNKRUPLAST5,n) 
scf_broke[is.na(scf_broke)] <- 0

#the proportion of bankruptcy
scf_broke <- scf_broke %>%
  mutate(broke = has/(no+has))
#the average proportion of bankruptcy with and without loan
scf_broke %>%
  group_by(LOAN)%>%
  summarise(mean(broke))

chart8

ggplot(scf_broke,aes(x = YEAR, y = broke*100, group = LOAN, color = LOAN))+
  geom_line(size = 1)+
  geom_point(size = 3)+
  geom_hline(yintercept = c(5.12,2.85), 
             lty=2,color = c("#FFCC66", "#CC6600"))+ 
  #add the average line to the chart
  geom_text(aes(label=round(broke*100,2), x = YEAR, y=broke*100, 
                group = LOAN), colour="grey10", size = 3, vjust = -1)+
  scale_x_continuous(name = "Survey Year",
                       limits = c(1995, 2019),
                       breaks = seq(1995, 2019, by = 3),
                       expand = c(0, 0))+
  scale_y_continuous(name = "The proportion of bankruptcy",
                     limits = c(2,6),
                     breaks = seq(2,6,by=1))+
  scale_color_manual(name = "student loan",
                    values=c("#FFCC66", "#CC6600"))+
  theme_minimal()+
  theme(legend.title = element_blank(),
        legend.text = element_text(size = 10, color = "gray10"),
        legend.position = "top",
        plot.title = element_text(face = "bold", color = "black", size = 20))+
  annotate("text", x = c(2019,2019), y = c(5.12,2.85), adj=1, 
           label = c("5.12%", "2.85%"),color=c("#FFCC66", "#CC6600"))+
  ggtitle("8. Student Loan leads to a higher Bankruptcy")

The line graph shows how the proportion varies over time and the color indicates the difference of proportion in student loan status. The proportion of bankruptcy does not change in great scale from 1998 to 2016. The respondents with student loan do have a higher possibility (5.12%) of having bankruptcy compared with those who do not have a student loan (2.85%).

Chart8 displays the difference in bankruptcy proportion with and without loan status by line chart. However, since there is no obvious trend over time, I suppose bar chart also matches this topic.

food expense and go broke

Two kinds of charts are used in this discussion. Chart9 is a series of pie charts and chart10 is a stacked bar chart.

dataset

scf_food1 <- scf %>% #bankruptcy and food expense
  select(BNKRUPLAST5,FOODDELV, FOODHOME, FOODAWAY) %>%
  group_by(BNKRUPLAST5) %>%
  summarise(delivery = mean(FOODDELV), home = mean(FOODHOME), away = mean(FOODAWAY)) %>%
  gather(key = "key", value = "value", delivery, away, home)%>%
  mutate(order = c(3,3,2,2,1,1)) #order for the plot

scf_food1$broke <- factor(scf_food1$BNKRUPLAST5,
                                levels = c("1","0"),
                                labels = c("has bankruptcy",
                                           "no bankruptcy"))

scf_food2 <- scf %>% #foreclose and food expense
  select(FORECLLAST5,FOODDELV, FOODHOME, FOODAWAY) %>%
  group_by(FORECLLAST5) %>%
  summarise(delivery = mean(FOODDELV), home = mean(FOODHOME), away = mean(FOODAWAY)) %>%
  gather(key = "key", value = "value", delivery, away, home)%>%
  mutate(order = c(3,3,2,2,1,1))

scf_food2$broke <- factor(scf_food2$FORECLLAST5,
                                levels = c("1","0"),
                                labels = c("has foreclose",
                                           "no foreclose"))

scf_food <- rbind(scf_food1[,2:5], scf_food2[,2:5])

chart9

ggplot(scf_food, aes(x="", y=value, fill=key))+
  geom_bar(width = 1, stat = "identity",position = "fill")+
  facet_wrap(~ broke)+
  coord_polar("y", start=0)+
  scale_fill_manual(values=c("#CC6600","#660000","#FFCC66"))+
  theme_minimal()+
  theme(axis.text = element_blank(),
        axis.ticks = element_blank(),
        panel.grid  = element_blank(),
        legend.title = element_blank(),
        legend.text = element_text(size = 10, color = "gray10"),
        legend.position = "right",
        plot.title = element_text(face = "bold", color = "black", size = 20))+
  ggtitle("9.Debt Struggles makes food at home")

Pie charts in chart9 show the proportion of different kinds of food expense in different broke status. No matter bankruptcy or foreclose, people without these problems spend more on food away from home.

chart10

#calculate the cumsum for the geom_text
scf_food_cum <- plyr::ddply(scf_food, "broke",
                   transform, ypos=cumsum(value))

ggplot(scf_food_cum,aes(x = broke))+
  geom_bar(aes(y = value, group = order, fill = key),
              stat = "identity", width = 0.5)+
  geom_text(aes(label = round(value), y = ypos, group = order),
            size = 3, color = "grey10", vjust = -1)+
  scale_y_continuous(name = "Expenses on Food",
                     limits = c(0,9000),
                     breaks = seq(0,9000, by = 2000))+
  xlab("Broke Status")+
  scale_fill_manual(values=c("#CC6600","#660000","#FFCC66"))+
  theme_minimal()+
  theme(legend.title = element_blank(),
        legend.text = element_text(size = 10, color = "gray10"),
        legend.position = "right",
        plot.title = element_text(face = "bold", color = "black", size = 20))+
  ggtitle("10.Debt Struggles makes food at home")

The stacked bar chart indicates the amount of the expenses on food together with the proportion. For the bankruptcy, people with the problem spend less on delivery and away and also in total on average. As for people struggling with foreclose, though they have a higher proportion of home food expense, they still spend more than 2,000 dollars in total than those without foreclose issue. We can tell from chart10 that there is a non-thrifty behavior in foreclose.

Chart10 has a better performance than chart9 because it provides some extra information of the amount of the spending as well as the proportion. It can show the actual non-thrifty behavior of respondents compared with chart9. Therefore, I recommand use stacked bar chart here.

5.Interaction

The scatter plot is usually not easy to tell apart from each point. Therefore, adding an interaction to the scatter plot is necessary. I made an interaction to chart6 so that readers can see the student loan, age and degree of each point.

ggplotly(age_edu)%>%
  layout(legend = list(x = 0.5, y = 1))

In original chart2, we can only see the proportion but not the actual average amount of different loans, so that’s why I add an interaction to thus chart.

ggplotly(loan, tooltip = c("loan","amount"))

6. Data Table

The table shows both the amount and proportion of loan from different category in survey year from the datatable. Readers can select the year and loan or even filter it by setting the range of amount and proportion.

pretty_headers <- 
  gsub("[.]", " ", colnames(scf_loan)) %>%
  str_to_title()

scf_loan %>%
  datatable(
    rownames = FALSE,
    colnames = pretty_headers,
    filter = list(position = "top"),
    options = list(language = list(sSearch = "Filter:"))
  )
LS0tDQp0aXRsZTogImh3MDEiDQphdXRob3I6ICJaaWppbiBaaG91Ig0KZGF0ZTogIjIwMjAvMi8xNiINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoNCmltcG9ydCBwYWNrYWdlcw0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ3JpZCkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShodG1sd2lkZ2V0cykNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShwdXJycikNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkoRFQpDQpgYGANCg0KaW1wb3J0IGRhdGENCmBgYHtyfQ0Kc2NmIDwtIHJlYWQudGFibGUoInN1cnZleV9TQ0YudHh0Iiwgc2VwID0gIiwiLCBoZWFkZXIgPSBUUlVFKSANCmBgYA0KDQojIyAxLiBEZWJ0IG92ZXIgdGltZQ0KIyMjIERlYnQgYW5kIGRlYnQgcmF0aW8gb3ZlciB0aW1lDQoNCioqZGF0YSBzZXQqKg0KYGBge3J9DQpzY2ZfZGVidCA8LSBzY2YgJT4lDQogIHNlbGVjdChDQVNFSUQsWUVBUixERUJULEFTU0VULEVETl9JTlNULCBMRVZSQVRJTywgREVCVDJJTkMpICU+JQ0KICBncm91cF9ieShZRUFSKSAlPiUgDQogIHN1bW1hcmlzZShkZWJ0X2luY29tZSA9IG1lYW4oREVCVDJJTkMpLA0KICAgICAgICAgICAgZGVidF9hc3NldD0gbWVhbihMRVZSQVRJTyksDQogICAgICAgICAgICBhdmVyYWdlX2RlYnQgPSBtZWFuKERFQlQpKSAlPiUNCiAgbXV0YXRlKGF2ZXJhZ2VfZGVidCA9IGF2ZXJhZ2VfZGVidC8xMDAwKSNtYWtlIGl0IGJ5IDEwMDAgZG9sbGFycw0KYGBgDQoNCioqY2hhcnQxKioNCmBgYHtyfQ0KZ2dwbG90KHNjZl9kZWJ0KSsNCiAgZ2VvbV9iYXIoYWVzKHg9WUVBUiwgeT0gYXZlcmFnZV9kZWJ0LCBmaWxsPSJhdmVyYWdlIGRlYnQiKSwNCiAgICAgICAgICAgICBzdGF0PSJpZGVudGl0eSIsIHdpZHRoID0gMSkrDQogIGdlb21fbGluZShhZXMoeD1ZRUFSLCB5PWRlYnRfYXNzZXQqMjAwLA0KICAgICAgICAgICAgICBjb2xvciA9ICJkZWJ0L2Fzc2V0IiksDQogICAgICAgICAgICAgIGdyb3VwID0gMSwgc2l6ZSA9IDEuMikrDQogIGdlb21fdGV4dChhZXMobGFiZWw9cm91bmQoZGVidF9hc3NldCwyKSwgDQogICAgICAgICAgICAgICAgeD1ZRUFSLHk9ZGVidF9hc3NldCoyMDApLA0KICAgICAgICAgICAgICBjb2xvdXI9ImdyZXkxMCIsIHNpemUgPSAzLCB2anVzdCA9IDIpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKGF2ZXJhZ2VfZGVidCksIA0KICAgICAgICAgICAgICAgIHg9WUVBUiwgeT1hdmVyYWdlX2RlYnQpLCANCiAgICAgICAgICAgICAgY29sb3VyPSJncmV5MTAiLCBzaXplID0gMywgdmp1c3QgPSAtMSkrDQogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlN1cnZleSBZZWFyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygxOTg2LCAyMDE5KSwNCiAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDE5ODksIDIwMTYsIGJ5ID0gMyksDQogICAgICAgICAgICAgICAgICAgICAgIGV4cGFuZCA9IGMoMCwgMCkpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiQXZlcmFnZSBEZWJ0IFxuYnkgMSwwMDAgZG9sbGFycyIsDQogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsNDAwKSwNCiAgICAgICAgICAgICAgICAgICAgIHNlYy5heGlzID0gc2VjX2F4aXMofi4vMjAwLCBuYW1lID0gImRlYnQvYXNzZXQgXG5bJV0iKSkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKCIgIiwgdmFsdWVzPWMoImRlYnQvYXNzZXQiID0gIiNDQzY2MDAiKSkrIA0KICAjYWRkIGEgc2Vjb25kIHktYXhpcyBmb3IgdGhlIHJhdGlvDQogIHNjYWxlX2ZpbGxfbWFudWFsKCIiLHZhbHVlcz0iI0ZGQ0M2NiIpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvciA9ICJncmF5MTAiKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjApKSsNCiAgZ2d0aXRsZSgiMS5EZWJ0IG92ZXIgdGltZSIpDQoNCmBgYA0KDQpJbiBjaGFydDEsIHRoZSBsaW5lIGNoYXJ0IHNob3dzIHRoZSB0cmVuZCBvZiBhdmVyYWdlIGRlYnQvYXNzZXQgcmF0aW8gZnJvbSAxOTg5IHRvIDIwMTYgYW5kIHRoZSBiYXIgY2hhcnQgc2hvd3MgdGhlIHRyZW5kIG9mIGF2ZXJhZ2UgZGVidCBmcm9tIDE5ODkgdG8gMjAxNi4gICANCkFsdGhvdWdoIHRoZSBhdmVyYWdlIGFtb3VudCBvZiBkZWJ0IGZsdWN0dWF0ZWQsIGl0IGRpZCBub3QgbWFrZSBhIGdyZWF0IGluY3JlYXNlIG92ZXIgdGhlIHllYXJzLiBIb3dldmVyLCB0aGUgZGVidC10by1hc3NldCByYXRpbyBpbmNyZWFzZWQgaW4gYSBncmVhdCBzY2FsZSBvdmVyIHRpbWUgYW5kIGV2ZW4gZ290IG92ZXIgMSBhZnRlciAyMDEwLiAgICANClRoZSBjb21iaW5hdGlvbiBvZiBsaW5lIGFuZCBiYXIgY2hhcnQgY2FuIHNob3cgdGhlIGFtb3VudCBvZiBkZWJ0IGFuZCB0aGUgdHJlbmQgb2YgcmF0aW8gb3ZlciB5ZWFyIGF0IHRoZSBzYW1lIHRpbWUgdGhlcmVmb3JlIHRoaXMgY2hhcnQgaXMgcHJvcGVyIGZvciB0aGUgcmVzZWFyY2guDQoNCg0KIyMjIFRoZSBwcm9wb3J0aW9uIG9mIFN0dWRlbnQgbG9hbg0KDQoqKmRhdGFzZXQqKg0KYGBge3J9DQpzY2ZfbG9hbiA8LSBzY2YgJT4lDQogIHNlbGVjdChDQVNFSUQsIFlFQVIsIERFQlQsIEVETl9JTlNULCBOSF9NT1JULCBPVEhMT0MsIENDQkFMLCBJTlNUQUxMLCBWRUhfSU5TVCkgJT4lDQogIGdyb3VwX2J5KFlFQVIpICU+JQ0KICBzdW1tYXJpc2UoZWR1Y2F0aW9uID0gcm91bmQobWVhbihFRE5fSU5TVCksMiksDQogICAgICAgICAgICBtb3J0Z2FnZSA9IHJvdW5kKG1lYW4oTkhfTU9SVCksMiksDQogICAgICAgICAgICBvdGhlciA9IHJvdW5kKG1lYW4oT1RITE9DKSwyKSwNCiAgICAgICAgICAgIGBjcmVkaXQgY2FyZGAgPSByb3VuZChtZWFuKENDQkFMKSwyKSwNCiAgICAgICAgICAgIGluc3RhbGxtZW50ID0gcm91bmQobWVhbihJTlNUQUxMKSwyKSwNCiAgICAgICAgICAgIHZlaGljbGUgPSByb3VuZChtZWFuKFZFSF9JTlNUKSwyKSklPiUNCiAgZ2F0aGVyKGtleSA9ICJsb2FuIiwgdmFsdWUgPSAiYW1vdW50IiwgZWR1Y2F0aW9uLCBtb3J0Z2FnZSxvdGhlcixgY3JlZGl0IGNhcmRgLGluc3RhbGxtZW50LHZlaGljbGUpICU+JQ0KICBzcGxpdCguJFlFQVIpJT4lDQogIG1hcCh+bXV0YXRlKC4scHJvcCA9IHJvdW5kKC4kYW1vdW50L3N1bSguJGFtb3VudCksMikpKSU+JSANCiAgI2NhbGN1bGF0ZSB0aGUgcHJvcG9ydGlvbiBieSB5ZWFyDQogIGJpbmRfcm93cygpDQoNCnNjZl9sb2FuJGxvYW4gPC0gZmFjdG9yKHNjZl9sb2FuJGxvYW4sDQogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygibW9ydGdhZ2UiLCJpbnN0YWxsbWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidmVoaWNsZSIsImNyZWRpdCBjYXJkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvdGhlciIsImVkdWNhdGlvbiIpKSANCiNlZHVjYXRpb24gc2hvdWxkIGJlIHRoZSBsYXN0IGxldmVsIGluIG9yZGVyIHRvIG1ha2UgdGhlIGNoYW5nZXMgb2YgcHJvcG9ydGlvbiBjbGVhcg0KYGBgDQoNCioqY2hhcnQyKioNCmBgYHtyfQ0KbG9hbiA8LSBnZ3Bsb3Qoc2NmX2xvYW4pKw0KICBnZW9tX2NvbChhZXMoeCA9IFlFQVIsIHkgPSBhbW91bnQsIGZpbGwgPSBsb2FuKSxwb3NpdGlvbiA9ICJmaWxsIiwgd2lkdGggPSAxKSsNCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiU3VydmV5IFllYXIiLA0KICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDE5ODYsIDIwMTkpLA0KICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMTk4OSwgMjAxNiwgYnkgPSAzKSwNCiAgICAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gYygwLCAwKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJwcm9wb3J0aW9uIikrDQogIGNvb3JkX2ZsaXAoKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0ZGQ0M2NiIsIiNGRjk5MDAiLCIjQ0M2NjAwIiwiI0NDNjYzMyIsIiM5OTMzMDAiLCIjMzMwMDAwIikpICsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChucm93ID0gMSkpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IDAuMDUsDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG9yID0gImdyYXkxMCIpLA0KICAgICAgICBsZWdlbmQua2V5LmhlaWdodD11bml0KDEsImxpbmUiKSwNCiAgICAgICAgbGVnZW5kLmtleS53aWR0aD11bml0KDEsImxpbmUiKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMCkpKw0KICBnZ3RpdGxlKCIyLlByb3BvcnRpb24gb2YgTG9hbnMiKQ0KDQpsb2FuDQpgYGANCg0KQ2hhcnQyIHNob3dzIHRoZSBwcm9wb3J0aW9uIG9mIHRoZSBhdmVyYWdlIG9mIGRpZmZlcmVudCBsb2FucyBldmVyeSBzdXJ2ZXkgeWVhci4gICAgDQpDb21wYXJpbmcgd2l0aCBvdGhlciB0eXBlIG9mIGxvYW5zLCBzdHVkZW50IGxvYW4gb25seSB0YWtlcyBhIHNtYWxsIHByb3BvcnRpb24gaW4gZGVidCAodGhlIGxhcmdlc3QgaXMgYWJvdXQgMyUgaW4gMjAxNiksIGJ1dCBpdCBnb3QgbW9yZSBpbXBvcnRhbnQgZnJvbSAxOTg5IHRvIDIwMTYuIE1vcnRhZ2UgbG9hbiBhbmQgaW5zdGFsbG1lbnQgbG9hbiBhcmUgdGhlIHRvcCAyIGxvYW4gYW1vbmcgYWxsIHRoZSBsb2Fucy4gTW9ydGFnZSBsb2FuIHRha2VzIG1vcmUgdGhhbiBhIGhhbGYgcHJvcG9ydGlvbiBvZiB0aGUgZGVidCBpbiBtb3N0IG9mIHRoZSBzdXJ2ZXkgeWVhcnMuDQoNCg0KIyMjIFN0dWRlbnQgTG9hbiBvdmVyIHRpbWUNCg0KKipkYXRhc2V0KioNCmBgYHtyfQ0Kc2NmX2VkdSA8LSBzY2YgJT4lDQogIHNlbGVjdChDQVNFSUQsWUVBUixERUJULEFTU0VULEVETl9JTlNUKSAlPiUNCiAgZmlsdGVyKERFQlQgIT0gMCkgJT4lDQogIG11dGF0ZShlZHVfcmF0aW8gPSBFRE5fSU5TVC9ERUJUKSAlPiUNCiAgZ3JvdXBfYnkoWUVBUikgJT4lDQogIHN1bW1hcmlzZShhdmVyYWdlX2VkdV9yYXRpbyA9IG1lYW4oZWR1X3JhdGlvKSxhdmVyYWdlX2VkdSA9IG1lYW4oRUROX0lOU1QpKQ0KYGBgDQoNCioqY2hhcnQzKioNCmBgYHtyfQ0KZ2dwbG90KHNjZl9lZHUpICsgDQogIGdlb21fYmFyKGFlcyh4PVlFQVIsIHk9IGF2ZXJhZ2VfZWR1LCBmaWxsPSJlZHUiKSwNCiAgICAgICAgICAgICBzdGF0PSJpZGVudGl0eSIsIHdpZHRoID0gMSkrDQogIGdlb21fbGluZShhZXMoeD1ZRUFSLCB5PWF2ZXJhZ2VfZWR1X3JhdGlvKjEwMDAwMCwNCiAgICAgICAgICAgICAgY29sb3IgPSAicmF0aW8iKSwNCiAgICAgICAgICAgICAgZ3JvdXAgPSAxLCBzaXplID0gMS4yKSsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZChhdmVyYWdlX2VkdV9yYXRpbyoxMDAsMiksIA0KICAgICAgICAgICAgICAgIHg9WUVBUix5PWF2ZXJhZ2VfZWR1X3JhdGlvKjEwMDAwMCksDQogICAgICAgICAgICAgIGNvbG91cj0iZ3JleTEwIiwgc2l6ZSA9IDMsIHZqdXN0ID0gLTEpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKGF2ZXJhZ2VfZWR1KSwgDQogICAgICAgICAgICAgICAgeD1ZRUFSLCB5PWF2ZXJhZ2VfZWR1KSwgDQogICAgICAgICAgICAgIGNvbG91cj0iZ3JleTEwIiwgc2l6ZSA9IDMsIHZqdXN0ID0gLTEpKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJTdXJ2ZXkgWWVhciIsDQogICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMTk4NiwgMjAxOSksDQogICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgxOTg5LCAyMDE2LCBieSA9IDMpLA0KICAgICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBjKDAsIDApKSArDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkF2ZXJhZ2UgRWR1Y2F0aW9uIExvYW4iLA0KICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLDE1MDAwKSwNCiAgICAgICAgICAgICAgICAgICAgIHNlYy5heGlzID0gc2VjX2F4aXMofi4vMTAwMCxuYW1lID0gImVkdWNhdGlvbiBsb2FuL2RlYnQgXG5bJV0iKSkrDQogIHNjYWxlX2NvbG91cl9tYW51YWwoIiAiLCB2YWx1ZXM9YygicmF0aW8iID0gIiNDQzY2MDAiKSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKCIiLHZhbHVlcz0iI0ZGQ0M2NiIpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvciA9ICJncmF5MTAiKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjApKSsNCiAgZ2d0aXRsZSgiRWR1Y2F0aW9uIExvYW4gb3ZlciB0aW1lIikNCmBgYA0KDQpJbiBjaGFydDMsIHRoZSBsaW5lIGNoYXJ0IHNob3dzIHRoZSB0cmVuZCBvZiBhdmVyYWdlIHN0dWRlbnRfbG9hbi9kZWJ0IHJhdGlvIGZyb20gMTk4OSB0byAyMDE2IGFuZCB0aGUgYmFyIGNoYXJ0IHNob3dzIHRoZSB0cmVuZCBvZiBhdmVyYWdlIHN0dWRlbnQgbG9hbiBmcm9tIDE5ODkgdG8gMjAxNi4gICAgDQpUaGUgcHJvcG9ydGlvbiBvZiB0aGUgU3R1ZGVudCBMb2FuIGluIHRoZSBsaW5lIGdyYXBoIGlzIGNhbGN1bGF0ZWQgYnkgRUROX0lOU1QvREVCVC4gTm90ZWQgdGhhdCB0aGVyZSBhcmUgbWFueSByZXNwb25kZW50cyB3aXRob3V0IGFueSBkZWJ0LCBzbyB0aGVzZSByZXNwb25kZW50cyBhcmUgcmVtb3ZlZCBmcm9tIHRoaXMgYW5hbHlzaXMuIFRoZSBwcm9wb3J0aW9ucyBvZiBzdHVkZW50IGxvYW4gaW4gdGhpcyBsaW5lIGdyYXBoIGFyZSBsYXJnZXIgdGhhbiB0aGUgcHJvcG9ydGlvbnMgaW4gc3RhY2tlZCAxMDAlIGJhciBjaGFydCBhYm92ZSBiZWNhdXNlIG9mIHRoZSBkaWZmZXJlbnQgY2FsY3VsYXRpb24gbWV0aG9kcy4gVGhlIHByb3BvcnRpb24gYW5kIHRoZSBhdmVyYWdlIGFtb3VudCBvZiBzdHVkZW50IGxvYW4gaGF2ZSBiZWVuIGluY3JlYXNpbmcgb3ZlciB0aW1lLiAgICAgDQpSZWdhcmRsZXNzbmVzcyBvZiB0aGUgZGlmZmVyZW50IG51bm1iZXIgaW4gY2hhcnQyIGFuZCBjaGFydDMsIHRoZSBldmlkZW5jZSBzaG93cyB0aGF0IHN0dWRlbnQgbG9hbiBkb2VzIGJlY29tZSBtb3JlIGltcG9ydGFudCBvdmVyIHllYXJzLg0KDQpUaGUgY29tYmluYXRpb24gb2YgbGluZSBhbmQgYmFyIGNoYXJ0IGNhbiBzaG93IHRoZSBhbW91bnQgb2Ygc3R1ZGVudCBsb2FuIGFuZCB0aGUgdHJlbmQgb2YgcmF0aW8gb3ZlciB5ZWFyIGF0IHRoZSBzYW1lIHRpbWU7IGhvd2V2ZXIsIGl0IGNhbm5vdCBpbmRpY2F0ZXMgdGhlIG90aGVyIGtpbmRzIG9mIGxvYW5zIGFuZCB0aGVyZSBwcm9wb3J0aW9uIGluIHRoZSBkZWJ0LiBDaGFydDIgY2FuIGdpdmUgdGhlIHJlYWRlciBhIGRpcmVjdCBmZWVsaW5nIG9mIHRoZSBwcm9wb3J0aW9uIG9mIGVhY2ggbG9hbiBhbmQgdGhlIGNoYW5nZSBvZiBzdHVkZW50IGxvYW4gb3ZlciB5ZWFycy4gVGhlcmVmb3JlLCBJIHJlY29tbWFuZCBjaGFydDIgdG8gc2hvdyB0aGUgZ3Jvd2luZyBpbXBvcnRhbmNlIG9mIHN0dWRlbnQgbG9hbiBvdmVyIHRpbWUuDQoNCg0KIyMgMi5UZWxsIG1lIHdobyB5b3UgYXJlDQojIyMgR2V0IG1hcnJpZWQgYW5kIGtpZHMsIGdldCBzdGFibGUgYW5kIGJyb2tlLg0KDQpUaGlzIHRvcGljIGlzIGEgZGlzY3Vzc2lvbiBvZiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gc3R1ZGVudCBsb2FuIGFuZCB0aGUgbnVtYmVyIG9mIGtpZHMgaW4gZGlmZmVyZW50IHRoZSBtYXJpdGFsIHN0YXR1cyBpbiAyMDE2LiBJIHVzZSB0d28ga2luZHMgb2YgdmlzdWFsaXphdGlvbiBpbiB0aGlzIGRpc2N1c3Npb24uIFRoZSBmaXJzdCwgY2hhcnQ0LCBpcyBhIGJ1YmJsZSBjaGFydCB3aXRoIGZpdCBsaW5lIGJ5IHRoZSBtZXRob2Qgb2YgbG9lc3MuIFRoZSBzZWNvbmQsIGNoYXJ0NSwgaXMgYSBkb2RnZWQgYmFyIGNoYXJ0IHdpdGggdGhlIGZpdCBsaW5lLg0KDQoqKmRhdGFzZXQqKg0KYGBge3J9DQpzY2ZfMjAxNiA8LSBzY2YgJT4lDQogIGZpbHRlcihZRUFSID09IDIwMTYpJT4lDQogIHNlbGVjdChDQVNFSUQsWUVBUixERUJULEFTU0VULEVETl9JTlNULCBFRENMLCBBR0UsIEZBTVNUUlVDVCwgTUFSUklFRCxLSURTLEVEVUMsSEhTRVgsUkFDRSkNCg0Kc2NmXzIwMTYkTUFSUklFRCA8LSBmYWN0b3Ioc2NmXzIwMTYkTUFSUklFRCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIjEiLCIyIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNYXJyaWVkL0xpdmluZyB3aXRoIHBhcnRuZXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmVpdGhlciBtYXJyaWVkIG5vciBsaXZpbmcgd2l0aCBwYXJ0bmVyIikpDQoNCnNjZl9tYXJpdGFsIDwtIHNjZl8yMDE2ICU+JQ0KICBncm91cF9ieShNQVJSSUVELCBLSURTKSAlPiUNCiAgc3VtbWFyaXNlKGVkdV9sb2FuID0gbWVhbihFRE5fSU5TVCksIG4gPSBuKCkpDQojbiBmb3IgdGhlIG51bWJlciBvZiByZXNwb25kZW50cyBpbiB0aGlzIGNhdGVnb3J5DQpgYGANCmBgYHtyfQ0KI2NoZWNrIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2Ygc3R1ZGVudCBsb2FuIGluIGRpZmZlcmVudCBtYXJpdGFsIHN0YXR1cw0Kc2NmX21hcml0YWwgJT4lDQogIGdyb3VwX2J5KE1BUlJJRUQpJT4lDQogIHN1bW1hcmlzZShtZWFuID0gbWVhbihlZHVfbG9hbiksIHNkID0gc2QoZWR1X2xvYW4pKQ0KYGBgDQoNCioqY2hhcnQ0OiBidWJibGUgYW5kIGZpdCBsaW5lKioNCmBgYHtyfQ0KZ2dwbG90KHNjZl9tYXJpdGFsLGFlcyh4ID0gS0lEUykpKw0KICBnZW9tX3BvaW50KGFlcyh5ID0gZWR1X2xvYW4sIGdyb3VwID0gTUFSUklFRCwgDQogICAgICAgICAgICAgICAgIGNvbG9yID0gTUFSUklFRCwgc2l6ZSA9IG4pLCBhbHBoYSA9IDAuOCkrDQogIGdlb21fc21vb3RoKGFlcyh5ID0gZWR1X2xvYW4sIGdyb3VwID0gTUFSUklFRCwgY29sb3IgPSBNQVJSSUVEKSwNCiAgICAgICAgICAgICAgIG1ldGhvZCA9ICdsb2Vzcycsc2UgPSBGQUxTRSkrDQogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIk51bWJlciBvZiBLaWRzIiwNCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLDcsIGJ5ID0gMSkpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJBdmVyYWdlIFN0dWRlbnQgTG9hbiIsDQogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwxMjUwMCwgYnkgPSAyNTAwKSkrDQogIHNjYWxlX2NvbG91cl9tYW51YWwobmFtZSA9ICJNYXJpdGFsIFN0YXR1cyIsIA0KICAgICAgICAgICAgICAgICAgICAgIHZhbHVlcz1jKCIjRkZDQzY2IiwgIiNDQzY2MDAiKSkrDQogIHNjYWxlX3NpemUobmFtZSA9ICJOdW1iZXIgb2YgT2JzZXJ2YXRpb25zIiwNCiAgICAgICAgICAgICByYW5nZSA9IGMoNCwxMikpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3IgPSAiZ3JheTEwIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjApKSsNCiAgZ2d0aXRsZSgiNC5HZXQgbWFycmllZCBhbmQga2lkcywgZ2V0IHN0YWJsZSBhbmQgYnJva2UiKQ0KDQpgYGANCg0KVGhlIGZpdCBsaW5lIGFuZCB0aGUgbG9jYXRpb24gb2YgdGhlIGJ1YmJsZSBpbiBjaGFydDQgc2hvdyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIG51bWJlciBvZiBraWRzIGFuZCB0aGUgc3R1ZGVudCBsb2FuLiBUaGUgY29sb3Igc2hvd3MgdGhlIGRpZmZlcmVudCBtYXJpdGFsIHN0YXR1cyBhbmQgdGhlIHNpemUgb2YgdGhlIGJ1YmJsZSBzaG93cyB0aGUgbnVtYmVyIG9mIHJlc3BvbmRlbnRzIGluIGVhY2ggY2F0ZWdvcnkgd2hpY2ggaW5kaWNhdGVzIHRoZSBiaWFzIG9mIHRoaXMgYW5hbHlzaXMuICAgDQpUaGUgc3RhYmlsaXR5IGhlcmUgZG9lcyBub3QgbWVhbiB0aGF0IG1hcnJpYWdlIGhlbHBzIGluIHNhdmluZyBtb25leSB0byBtYWtlIGEgbW9yZSBzdGFibGUgbGlmZS4gSW4gZmFjdCwgZ2V0IG1hcnJpZWQgbWFrZXMgYSBzdGFibGUgYW5kIGhpZ2ggZXhwZW5zZSBmb3IgZWR1Y2F0aW9uYWwgbG9hbnMgbm8gbWF0dGVyIGhvdyBtYW55IGNoaWxkcmVuIHRoZSBob3VzZWhvbGQgaGFzLiBUaGUgYXZlcmFnZSBlZHVjYXRpb24gbG9hbiBpbiB0aGUgbWFycmllZCByZXNwb25kZW50IGlzIDgzNzguMjQgZG9sbGFycywgd2hpY2ggaXMgYWJvdXQgMjAwMCBkb2xsYXJzIGhpZ2hlciB0aGFuIHRoZSBvdGhlcnMuIEFsc28sIHdlIGNhbiB0ZWxsIGZyb20gdGhlIGxvd2VyIHN0YW5kYXJkIGRldmlhdGlvbiB0aGF0IHRoZSBoaWdoZXIgc3RhYmlsaXR5IG9mIGV4cGVuc2VzIG9uIGVkdWNhdGlvbmFsIGxvYW5zIHRoYXQgbWFycmllZCBwZW9wbGUgaGF2ZS4gICAgIA0KQXMgZm9yIHRoZSBwZW9wbGUgd2hvIGFyZSBuZWl0aGVyIG1hcnJpZWQgb3IgbGl2aW5nIHdpdGggYSBwYXJ0bmVyLCB0aGUgYXZlcmFnZSBlZHVjYXRpb25hbCBsb2FuIGV4cGVuc2VzIGNhbiBoaXQgdGhlIHRvcCBhdCBhbG1vc3QgMTIwMDAgZG9sbGFycyBpZiB0aGV5IGhhdmUgMyBjaGlsZHJlbjsgaG93ZXZlciwgaXQgZ29lcyBkb3duIG9uIGEgbGFyZ2Ugc2NhbGUgd2hlbiB0aGUgbnVtYmVyIG9mIGNoaWxkcmVuIGlzIG92ZXIgMy4gICAgICAgDQpBZGRpdGlvbmFsbHksIG5vIG1hdHRlciBtYXJyaWVkIG9yIG5vdCwgcGVvcGxlIHdpdGhvdXQga2lkcyB1c3VhbGx5IHBheSBmZXdlciBlZHVjYXRpb24gbG9hbnMgYXMgaXQgc2hvd3MgaW4gdGhlIGdyYXBoLiAgICAgDQpOb3RlZCB0aGF0IHRoZSByZXN1bHQgaGFzIGEgYmlhcyBiZWNhdXNlIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGlzIHJlbGF0aXZlbHkgbGltaXRlZCB0aGUgbW9yZSBjaGlsZHJlbiB0aGUgaG91c2Vob2xkcyBoYXZlLiANCg0KKipjaGFydDU6IGJhciBjaGFydCBhbmQgZml0IGxpbmUqKg0KYGBge3J9DQpnZ3Bsb3Qoc2NmX21hcml0YWwsYWVzKHggPSBLSURTKSkrDQogIGdlb21fYmFyKGFlcyh5ID0gZWR1X2xvYW4sIGdyb3VwID0gTUFSUklFRCwgZmlsbCA9IE1BUlJJRUQpLA0KICAgICAgICAgICAgICBzaXplICA9IDQsIHdpZHRoID0gMC41LCBzdGF0ID0gImlkZW50aXR5IiwgYWxwaGEgPTAuNywNCiAgICAgICAgICAgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoKSkrDQogIGdlb21fc21vb3RoKGFlcyh5ID0gZWR1X2xvYW4sIGdyb3VwID0gTUFSUklFRCwgY29sb3IgPSBNQVJSSUVEKSwNCiAgICAgICAgICAgICAgIG1ldGhvZCA9ICdsb2Vzcycsc2UgPSBGQUxTRSkrDQogIGdlb21fdGV4dChhZXMobGFiZWw9cm91bmQoZWR1X2xvYW4pLCANCiAgICAgICAgICAgICAgICB5PWVkdV9sb2FuLCBncm91cCA9IE1BUlJJRUQpLCANCiAgICAgICAgICAgIGNvbG91cj0iZ3JleTEwIiwgc2l6ZSA9IDMsIHZqdXN0ID0gLTEsIA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpKSsNCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiTnVtYmVyIG9mIEtpZHMiLA0KICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsNywgYnkgPSAxKSkrDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkF2ZXJhZ2UgU3R1ZGVudCBMb2FuIiwNCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCwxNDAwMCksDQogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwxNTAwMCwgYnkgPSAyNTAwKSkrDQogIHNjYWxlX2NvbG91cl9tYW51YWwobmFtZSA9ICJhdmVyYWdlIGVkdSBsb2FuIiwgDQogICAgICAgICAgICAgICAgICAgICAgdmFsdWVzPWMoIiNDQzY2NjYiLCIjOTkwMDMzIikpKw0KICBzY2FsZV9maWxsX21hbnVhbChuYW1lID0gImF2ZXJhZ2UgZWR1IGxvYW4iLCANCiAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXM9YygiI0ZGQ0M2NiIsICIjQ0M2NjAwIikpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvciA9ICJncmF5MTAiKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjApKSsNCiAgZ2d0aXRsZSgiNS5HZXQgbWFycmllZCBhbmQga2lkcywgZ2V0IHN0YWJsZSBhbmQgYnJva2UiKQ0KYGBgDQoNCldlIGNhbiBkcmF3IHRoZSBzYW1lIGNvbmNsdXNpb24gYXMgY2hhcnQ0IGZyb20gY2hhcnQ1IGV4Y2VwdCBmb3IgdGhlIG51bWJlciBvZiByZXNwb25kZW50cyBpbiBlYWNoIGNhdGVnb3J5LiBBZGRpdGlvbmFsbHksIHRoZSBiYXIgY2hhcnQgaW4gY2hhcnQ1IGNhbiB0ZWxsIHRoZSBhbW91bnQgb2YgYXZlcmFnZSBzdHVkZW50IGxvYW4gbW9yZSBjbGVhcmx5LiAgICANCg0KRm9yIGdldHRpbmcgbW9yZSBpbmZvcm1hdGlvbiwgSSB0aGluayBjaGFydDQgaXMgYmV0dGVyIHRoYW4gY2hhcnQ1IGluIHRoaXMgdG9waWMuIENoYXJ0NCBub3Qgb25seSBkaXNwbGF5cyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gZGVidCwga2lkcyBhbmQgbWFycmlhZ2UsIGJ1dCBzaG93cyB0aGUgbnVtYmVyIG9mIHBlb3BsZSBpbiBlYWNoIGNhdGVnb3J5IGluIHRoZSBzdXJ2ZXkuDQoNCg0KIyMjIFlvdW5nLCBTbWFydCBidXQgUG9vcg0KDQpUaGlzIHRvcGljIGRpc2N1c3NlcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYWdlIGFuZCBzdHVkZW50IGxvYW4gaW4gZGlmZmVyZW50IGVkdWNhdGlvbiBiYWNrZ3JvdW5kIGluIDIwMTYgd2l0aCBzY2F0dGVyIGFuZCBmaXQgbGluZSAoY2hhcnQ2KS4NCg0KKipkYXRhc2V0KioNCmBgYHtyfQ0Kc2NmX2FnZSA8LSBzY2ZfMjAxNiAlPiUNCiAgZ3JvdXBfYnkoQUdFLCBFRENMKSU+JQ0KICBzdW1tYXJpc2UoZWR1X2xvYW4gPSByb3VuZChtZWFuKEVETl9JTlNUKSwyKSxuKCkpDQoNCnNjZl9hZ2UkZWR1IDwtIGZhY3RvcihzY2ZfYWdlJEVEQ0wsDQogICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIjEiLCIyIiwiMyIsIjQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTm8gaGlnaCBzY2hvb2wgZGlwbG9tYS9HRUQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIaWdoIHNjaG9vbCBkaXBsb21hL0dFRCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNvbWUgY29sbGVnZSIsIkNvbGxlZ2UgZGVncmVlIikpDQpgYGANCg0KKipjaGFydDYqKg0KYGBge3J9DQphZ2VfZWR1IDwtIGdncGxvdChzY2ZfYWdlLCBhZXMoeCA9IEFHRSx5ID0gZWR1X2xvYW4pKSsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBlZHUpLHNoYXBlID0gMSxzaXplID0gMixzdHJva2UgPSAxLjUpKw0KICBnZW9tX3Ntb290aChjb2xvciA9ICIjOTkwMDAwIiwgbWV0aG9kID0gImxvZXNzIiwgc2UgPSBGQUxTRSkrDQogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIkFnZSBvZiBIb3VzZWhvbGQiLA0KICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDE4LDk2LGJ5PTYpKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiQXZlcmFnZSBTdHVkZW50IExvYW4iLA0KICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsNTAwMDAsYnkgPSAxMDAwMCkpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiI0ZGQ0M2NiIsIiNGRjk5MDAiLCIjQ0M2NjAwIiwiIzY2MDAwMCIpKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3IgPSAiZ3JheTEwIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIwKSkrDQogIGdndGl0bGUoIjYuWW91bmcsIFNtYXJ0IGJ1dCBQb29yIikNCmFnZV9lZHUgDQpgYGANCg0KRWFjaCBwb2ludCBpbiB0aGUgc2NhdHRlciBwbG90IHNob3dzIHRoZSBhdmVyYWdlIHN0dWRlbnQgbG9hbiBpbiBhbiBjZXJ0YWluIGFnZSBhbmQgZWR1Y2F0aW9uIGJhY2tncm91bmQuIFRoZSBkYXJrZXIgb2YgdGhlIHBvaW50J3MgY29sb3IsIHRoZSBoaWdoZXIgZWR1Y2F0aW9uIHRoZSByZXNwb25kZW50IGdvdC4gVGhlIGZpdCBsaW5lIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhZ2UgYW5kIHN0dWRlbnQgbG9hbiBhcyBhIHdob2xlLiAgIA0KVGhlIGNvbG9yIGluIGNoYXJ0NiB0ZWxscyB0aGF0IHBlb3BsZSB3aXRoIGhpZ2ggZGVncmVlIHRlbmQgdG8gaGF2ZSBtb3JlIHN0dWRlbnQgbG9hbi4gRm9yIGluc3RhbmNlIHRoZSBhdmVyYWdlIHN0dWRlbnQgbG9hbiBvZiBjb2xsZWdlIGRlZ3JlZSBwZW9wbGUgYXQgYWdlIG9mIDI4IGNhbiBiZSBtb3JlIHRoYW4gNTUsMDAwIGRvbGxhcnMsIHdoaWxlIHRoZSBvbmUgd2l0aCBvdGhlciBkZWdyZWVzIGFyZSBhbGwgbGVzcyB0aGFuIDIwLDAwMCBkb2xsYXJzLiAgICANCkZvciBhbGwga2luZCBzIG9mIG9ic2VydmF0aW9ucywgdGhlIGF2ZXJhZ2Ugc3R1ZGVudCBsb2FuIGdvZXMgdXAgd2l0aCBhZ2UgYmVmb3JlIGFib3V0IDMwLCB0aGVuIGl0IGRlY3JlYXNlIGFzIGdldHRpbmcgb2xkZXIuIEFmdGVyIGFib3V0IDcwLCB0aGUgYXZlcmFnZSBhbW91bnQgb2Ygc3R1ZGVudCBsb2FuIGdldCB6ZXJvIG5vIG1hdHRlciB0aGUgZWR1Y2F0aW9uYWwgYmFja2dyb3VuZC4gICAgDQoNClRoZSBzY2F0dGVyIHBsb3Qgd2l0aCBjb2xvciBjYW4gZ2l2ZSByZWFkZXJzIGEgY2xlYXIgaW5mb3JtYXRpb24gb2YgdGhlIGVkdWNhdGlvbiBiYWNrZ3JvdW5kIHBhdHRlcm4gYW5kIHRoZSBmaXQgbGluZSBzaG93cyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYWdlIGFuZCBzdHVkZW50IGxvYW4gd2VsbC4gVGhlcmVmb3JlLCBDaGFydDYgaXMgc3VpdGFibGUgZm9yIHRoaXMgdG9waWMuDQoNCg0KIyMgMy5XZWFsdGggYW5kIEluY29tZSBEaXN0cmlidXRpb24NCg0KVGhpcyBzZWN0aW9uIGRpc2N1c3NlcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gc3R1ZGVudCBsb2FuIGFuZCBib3RoIG5ldHdvcnRoIGFuZCBpbmNvbWUgaW4gMjAxNiB3aXRoIHR3byBzaW1wbGUgYmFyIGNoYXJ0cyAoY2hhcnQ3KS4NCg0KKipkYXRhc2V0KioNCmBgYHtyfQ0Kc2NmX21vbmV5IDwtIHNjZiAlPiUNCiAgZmlsdGVyKFlFQVIgPT0gMjAxNiklPiUNCiAgc2VsZWN0KENBU0VJRCxZRUFSLERFQlQsQVNTRVQsRUROX0lOU1QsIElOQ09NRSwgSU5DQ0FULCBORVRXT1JUSCwgTldDQVQpDQoNCiNtYWtlIG5ldHdvcnRoIGFuZCBpbmNvbWUgaGF2ZSB0aGUgc2FtZSBudW1iZXIgb2YgY2F0ZWdvcmllcyBhbmQgY29udmVydCBpdCBpbnRvIHBlcmNlbnRpbGUgc2NhbGUuDQpzY2ZfbW9uZXkkTldDQVQgPC0gc2NmX21vbmV5JE5XQ0FUKjIwLTEwDQpzY2ZfbW9uZXkkSU5DQ0FUW3NjZl9tb25leSRJTkNDQVQgPT0gNl0gPC0gNQ0Kc2NmX21vbmV5JElOQ0NBVCA8LSBzY2ZfbW9uZXkkSU5DQ0FUKjIwLTEwDQpgYGANCmBgYHtyfQ0KI25ldHdvcnRoIHBlcmNlbnRpbGUgYW5kIHN0dWRlbnQgbG9hbg0Kc2NmX253IDwtIHNjZl9tb25leSAlPiUNCiAgZ3JvdXBfYnkoTldDQVQpICU+JQ0KICBzdW1tYXJpc2UobmV0d29ydGggPSBtZWRpYW4oTkVUV09SVEgpLCBlZHVfbG9hbiA9IG1lYW4oRUROX0lOU1QpKSU+JQ0KICBtdXRhdGUocGVyY2VudGlsZSA9IE5XQ0FUKSAlPiUNCiAgc2VsZWN0KHBlcmNlbnRpbGUsbmV0d29ydGgsZWR1X2xvYW4pJT4lDQogIGdhdGhlcihrZXkgPSAia2V5Iix2YWx1ZSA9ICJ2YWx1ZSIsbmV0d29ydGgpJT4lDQogIHNlbGVjdChwZXJjZW50aWxlLGtleSxlZHVfbG9hbikNCiNpbmNvbWUgcGVyY2VudGlsZSBhbmQgc3R1ZGVudCBsb2FuDQpzY2ZfaW5jIDwtIHNjZl9tb25leSAlPiUNCiAgZ3JvdXBfYnkoSU5DQ0FUKSAlPiUNCiAgc3VtbWFyaXNlKGluY29tZSA9IG1lZGlhbihJTkNPTUUpLCBlZHVfbG9hbiA9IG1lYW4oRUROX0lOU1QpKSU+JQ0KICBtdXRhdGUocGVyY2VudGlsZSA9IElOQ0NBVCklPiUNCiAgc2VsZWN0KHBlcmNlbnRpbGUsaW5jb21lLGVkdV9sb2FuKSU+JQ0KICBnYXRoZXIoa2V5ID0gImtleSIsdmFsdWUgPSAidmFsdWUiLGluY29tZSklPiUNCiAgc2VsZWN0KHBlcmNlbnRpbGUsa2V5LGVkdV9sb2FuKQ0KI2NvbWJpbmUNCnNjZl9tb25leTIgPC0gcmJpbmQoc2NmX253LHNjZl9pbmMpDQpgYGANCg0KKipjaGFydDcqKg0KYGBge3J9DQpnZ3Bsb3Qoc2NmX21vbmV5MikrDQogIGdlb21fYmFyKGFlcyh4ID0gcGVyY2VudGlsZSwgeSA9IGVkdV9sb2FuLCBncm91cCA9IGtleSwgZmlsbCA9IGtleSksIA0KICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAxMCkrDQogIGZhY2V0X3dyYXAofiBrZXkpKyAjbWFrZSBpdCBpbnRvIHR3byBzZXBlcmF0ZSBjaGFydHMNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZChlZHVfbG9hbiksIHggPSBwZXJjZW50aWxlLCB5PWVkdV9sb2FuLCANCiAgICAgICAgICAgICAgICBncm91cCA9IGtleSksIGNvbG91cj0iZ3JleTEwIiwgc2l6ZSA9IDMsIHZqdXN0ID0gLTEpKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJwZXJjZW50aWxlIiwNCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCwxMDApLA0KICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsMTAwLGJ5PTIwKSkrDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkF2ZXJhZ2UgU3R1ZGVudCBMb2FuIiwNCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCwxODAwMCkpKw0KICBzY2FsZV9maWxsX21hbnVhbChuYW1lID0gImNhdGVnb3J5IiwgDQogICAgICAgICAgICAgICAgICAgICAgdmFsdWVzPWMoIiNGRkNDNjYiLCAiI0NDNjYwMCIpKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3IgPSAiZ3JheTEwIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjApKSsNCiAgZ2d0aXRsZSgiNy5XZWFsdGggYW5kIEluY29tZSBEaXN0cmlidXRpb24iKQ0KDQpgYGANCg0KVGhlIGJhciBjaGFydCBvbiB0aGUgbGVmdCBpbiBjaGFydDcgc2hvd3MgdGhhdCB0aGUgYXZlcmFnZSBzdHVkZW50IGxvYW4gaW5jcmVhc2VzIHRoZW4gZGVjcmVhc2VzIGFzIGluY29tZSBnb2luZyB1cC4gUGVvcGxlIGluIDQwLTYwIHBlcmNlbnRpbGUgb2YgaW5jb21lIGhhdmUgdGhlIGhpZ2hlc3QgYXZlcmFnZSBzdHVkZW50IGxvYW4sIDkyNjYgZG9sbGFycy4gVGhpcyBtYXliZSBiZWNhdXNlIHRoZSBoaWdoZXItaW5jb21lIGNsYXNzIHRlbmRzIHRvIHNwZW5kIG1vcmUgb24gZWR1Y2F0aW9uIGJ1dCB0aGV5IGNhbiBwYXkgbW9yZSBvciBwYXkgb2ZmIHdpdGggdGhlcmUgb3duIGluY29tZSB3aXRob3V0IHRoZSBoZWxwIG9mIGRlYnQgd2hlbiB0aGUgaW5jb21lIGdldHMgZXZlbiBoaWdoZXIuIFBvb3IgbWlkZGxlIGNsYXNzOiggICAgDQpIb3dldmVyLCB0aGUgZGlzY3Vzc2lvbiBvbiBuZXR3b3J0aCBzaG93cyBhIHRvdGFsbHkgZGlmZmVyZW50IHBhdHRlcm4uIExlc3MgbmV0d29ydGggcmV2ZWFscyBtb3JlIGRlYnQsIGVzcGVjaWFsbHkgZmlyc3QgMjAlIChhdmVyYWdlIHN0dWRlbnQgbG9hbiBtb3JlIHRoYW4gMTcsMDAwIGRvbGxhcnMpIGFzIGl0IGRpc3BsYXlzIG9uIHRoZSByaWdodC4gUGVvcGxlIGZyb20gMjAlIHRvIDgwJSBwZXJjZW50aWxlIGhhdmUgYW4gYXZlcmFnZSBzdHVkZW50IGxvYW4gYmV0d2VlbiA0LDAwMCBhbmQgNiwwMDAgZG9sbGFycywgd2hpbGUgODAlIHRvIDEwMCUgaGF2ZSB0aGUgYXZlcmFnZSBsb2FuIGxlc3MgdGhhbiAyLDAwMCBkb2xsYXJzLg0KDQpUd28gc2VwZXJhdGUgYmFyIGNoYXJ0cyBjYW4gbWFrZSByZWFkZXIgdW5kZXJzdGFuZCB0aGUgc3R1ZGVudCBsb2FuIGluIGRpZmZlcmVudCBuZXR3b3J0aCBhbmQgaW5jb21lIGFuZCBjb21wYXJlIHRoZSBwYXR0ZXJucyBvZiB0aGVtIGVhc2lseS4gVGhlcmVmb3JlLCBjaGFydDcgaXMgcmVjb21tZW5kIGZvciBkaXNjdXNzaW5nIHdlYWx0aCBhbmQgaW5jb21lIGRpc3RyaWJ1dGlvbi4NCg0KDQojIyA0LkdvaW5nIGJyb2tlDQoNCiMjIyBCYW5rcnVwdGN5IGFuZCBTdHVkZW50IExvYW4NCg0KVGhpcyBwYXJ0IGRpc2N1c3NlcyB0aGUgcHJvcG9ydGlvbiBvZiBiYW5rcnVwdGN5IHdpdGggYW5kIHdpdGhvdXQgc3R1ZGVudCBsb2FucyBvdmVyIHRpbWUgYWZ0ZXIgMTk5OCBiZWNhdXNlIHRoZXJlIGlzIG5vIGJhbmtydXB0Y3kgcmVwb3J0ZWQgaW4gdGhlIG9yaWdpbmFsIGRhdGFzZXQgYmVmb3JlLiANCg0KKipkYXRhc2V0KioNCmBgYHtyfQ0Kc2NmX2Jyb2tlIDwtIHNjZiAlPiUNCiAgZmlsdGVyKFlFQVIgPj0gMTk5OCkgJT4lDQogIHNlbGVjdChZRUFSLEVETl9JTlNULCBCTktSVVBMQVNUNSkNCg0KI2RpdmlkZSBpbnRvIHR3byBjYXRlZ29yaWVzOiB3aXRoIGFuZCB3aXRob3V0IHN0dWRlbnQgbG9hbg0Kc2NmX2Jyb2tlJExPQU4gPC0gaWZlbHNlKHNjZl9icm9rZSRFRE5fSU5TVCAhPSAwLCAiaGFkIGxvYW4iLCAibm8gbG9hbiIpDQoNCnNjZl9icm9rZSRCTktSVVBMQVNUNSA8LSBmYWN0b3Ioc2NmX2Jyb2tlJEJOS1JVUExBU1Q1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCIxIiwiMCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJoYXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJubyIpKQ0KI2NvdW50IHRoZSBudW1iZXIgb2YgZWFjaCBjYXRlZ29yaWVzDQpzY2ZfYnJva2UgPC0gc2NmX2Jyb2tlICU+JQ0KICBncm91cF9ieShZRUFSLCBCTktSVVBMQVNUNSwgTE9BTiklPiUNCiAgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgc3ByZWFkKEJOS1JVUExBU1Q1LG4pIA0Kc2NmX2Jyb2tlW2lzLm5hKHNjZl9icm9rZSldIDwtIDANCg0KI3RoZSBwcm9wb3J0aW9uIG9mIGJhbmtydXB0Y3kNCnNjZl9icm9rZSA8LSBzY2ZfYnJva2UgJT4lDQogIG11dGF0ZShicm9rZSA9IGhhcy8obm8raGFzKSkNCmBgYA0KYGBge3J9DQojdGhlIGF2ZXJhZ2UgcHJvcG9ydGlvbiBvZiBiYW5rcnVwdGN5IHdpdGggYW5kIHdpdGhvdXQgbG9hbg0Kc2NmX2Jyb2tlICU+JQ0KICBncm91cF9ieShMT0FOKSU+JQ0KICBzdW1tYXJpc2UobWVhbihicm9rZSkpDQpgYGANCg0KKipjaGFydDgqKg0KYGBge3J9DQpnZ3Bsb3Qoc2NmX2Jyb2tlLGFlcyh4ID0gWUVBUiwgeSA9IGJyb2tlKjEwMCwgZ3JvdXAgPSBMT0FOLCBjb2xvciA9IExPQU4pKSsNCiAgZ2VvbV9saW5lKHNpemUgPSAxKSsNCiAgZ2VvbV9wb2ludChzaXplID0gMykrDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGMoNS4xMiwyLjg1KSwgDQogICAgICAgICAgICAgbHR5PTIsY29sb3IgPSBjKCIjRkZDQzY2IiwgIiNDQzY2MDAiKSkrIA0KICAjYWRkIHRoZSBhdmVyYWdlIGxpbmUgdG8gdGhlIGNoYXJ0DQogIGdlb21fdGV4dChhZXMobGFiZWw9cm91bmQoYnJva2UqMTAwLDIpLCB4ID0gWUVBUiwgeT1icm9rZSoxMDAsIA0KICAgICAgICAgICAgICAgIGdyb3VwID0gTE9BTiksIGNvbG91cj0iZ3JleTEwIiwgc2l6ZSA9IDMsIHZqdXN0ID0gLTEpKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJTdXJ2ZXkgWWVhciIsDQogICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMTk5NSwgMjAxOSksDQogICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgxOTk1LCAyMDE5LCBieSA9IDMpLA0KICAgICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBjKDAsIDApKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiVGhlIHByb3BvcnRpb24gb2YgYmFua3J1cHRjeSIsDQogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIsNiksDQogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMiw2LGJ5PTEpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWUgPSAic3R1ZGVudCBsb2FuIiwNCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzPWMoIiNGRkNDNjYiLCAiI0NDNjYwMCIpKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3IgPSAiZ3JheTEwIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIwKSkrDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IGMoMjAxOSwyMDE5KSwgeSA9IGMoNS4xMiwyLjg1KSwgYWRqPTEsIA0KICAgICAgICAgICBsYWJlbCA9IGMoIjUuMTIlIiwgIjIuODUlIiksY29sb3I9YygiI0ZGQ0M2NiIsICIjQ0M2NjAwIikpKw0KICBnZ3RpdGxlKCI4LiBTdHVkZW50IExvYW4gbGVhZHMgdG8gYSBoaWdoZXIgQmFua3J1cHRjeSIpDQpgYGANCg0KVGhlIGxpbmUgZ3JhcGggc2hvd3MgaG93IHRoZSBwcm9wb3J0aW9uIHZhcmllcyBvdmVyIHRpbWUgYW5kIHRoZSBjb2xvciBpbmRpY2F0ZXMgdGhlIGRpZmZlcmVuY2Ugb2YgcHJvcG9ydGlvbiBpbiBzdHVkZW50IGxvYW4gc3RhdHVzLiBUaGUgcHJvcG9ydGlvbiBvZiBiYW5rcnVwdGN5IGRvZXMgbm90IGNoYW5nZSBpbiBncmVhdCBzY2FsZSBmcm9tIDE5OTggdG8gMjAxNi4gVGhlIHJlc3BvbmRlbnRzIHdpdGggc3R1ZGVudCBsb2FuIGRvIGhhdmUgYSBoaWdoZXIgcG9zc2liaWxpdHkgKDUuMTIlKSBvZiBoYXZpbmcgYmFua3J1cHRjeSBjb21wYXJlZCB3aXRoIHRob3NlIHdobyBkbyBub3QgaGF2ZSBhIHN0dWRlbnQgbG9hbiAoMi44NSUpLiANCg0KQ2hhcnQ4IGRpc3BsYXlzIHRoZSBkaWZmZXJlbmNlIGluIGJhbmtydXB0Y3kgcHJvcG9ydGlvbiB3aXRoIGFuZCB3aXRob3V0IGxvYW4gc3RhdHVzIGJ5IGxpbmUgY2hhcnQuIEhvd2V2ZXIsIHNpbmNlIHRoZXJlIGlzIG5vIG9idmlvdXMgdHJlbmQgb3ZlciB0aW1lLCBJIHN1cHBvc2UgYmFyIGNoYXJ0IGFsc28gbWF0Y2hlcyB0aGlzIHRvcGljLg0KDQoNCiMjIyBmb29kIGV4cGVuc2UgYW5kIGdvIGJyb2tlDQoNClR3byBraW5kcyBvZiBjaGFydHMgYXJlIHVzZWQgaW4gdGhpcyBkaXNjdXNzaW9uLiBDaGFydDkgaXMgYSBzZXJpZXMgb2YgcGllIGNoYXJ0cyBhbmQgY2hhcnQxMCBpcyBhIHN0YWNrZWQgYmFyIGNoYXJ0Lg0KDQoqKmRhdGFzZXQqKg0KYGBge3J9DQpzY2ZfZm9vZDEgPC0gc2NmICU+JSAjYmFua3J1cHRjeSBhbmQgZm9vZCBleHBlbnNlDQogIHNlbGVjdChCTktSVVBMQVNUNSxGT09EREVMViwgRk9PREhPTUUsIEZPT0RBV0FZKSAlPiUNCiAgZ3JvdXBfYnkoQk5LUlVQTEFTVDUpICU+JQ0KICBzdW1tYXJpc2UoZGVsaXZlcnkgPSBtZWFuKEZPT0RERUxWKSwgaG9tZSA9IG1lYW4oRk9PREhPTUUpLCBhd2F5ID0gbWVhbihGT09EQVdBWSkpICU+JQ0KICBnYXRoZXIoa2V5ID0gImtleSIsIHZhbHVlID0gInZhbHVlIiwgZGVsaXZlcnksIGF3YXksIGhvbWUpJT4lDQogIG11dGF0ZShvcmRlciA9IGMoMywzLDIsMiwxLDEpKSAjb3JkZXIgZm9yIHRoZSBwbG90DQoNCnNjZl9mb29kMSRicm9rZSA8LSBmYWN0b3Ioc2NmX2Zvb2QxJEJOS1JVUExBU1Q1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCIxIiwiMCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJoYXMgYmFua3J1cHRjeSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5vIGJhbmtydXB0Y3kiKSkNCg0Kc2NmX2Zvb2QyIDwtIHNjZiAlPiUgI2ZvcmVjbG9zZSBhbmQgZm9vZCBleHBlbnNlDQogIHNlbGVjdChGT1JFQ0xMQVNUNSxGT09EREVMViwgRk9PREhPTUUsIEZPT0RBV0FZKSAlPiUNCiAgZ3JvdXBfYnkoRk9SRUNMTEFTVDUpICU+JQ0KICBzdW1tYXJpc2UoZGVsaXZlcnkgPSBtZWFuKEZPT0RERUxWKSwgaG9tZSA9IG1lYW4oRk9PREhPTUUpLCBhd2F5ID0gbWVhbihGT09EQVdBWSkpICU+JQ0KICBnYXRoZXIoa2V5ID0gImtleSIsIHZhbHVlID0gInZhbHVlIiwgZGVsaXZlcnksIGF3YXksIGhvbWUpJT4lDQogIG11dGF0ZShvcmRlciA9IGMoMywzLDIsMiwxLDEpKQ0KDQpzY2ZfZm9vZDIkYnJva2UgPC0gZmFjdG9yKHNjZl9mb29kMiRGT1JFQ0xMQVNUNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiMSIsIjAiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiaGFzIGZvcmVjbG9zZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5vIGZvcmVjbG9zZSIpKQ0KDQpzY2ZfZm9vZCA8LSByYmluZChzY2ZfZm9vZDFbLDI6NV0sIHNjZl9mb29kMlssMjo1XSkNCmBgYA0KDQoqKmNoYXJ0OSoqDQpgYGB7cn0NCmdncGxvdChzY2ZfZm9vZCwgYWVzKHg9IiIsIHk9dmFsdWUsIGZpbGw9a2V5KSkrDQogIGdlb21fYmFyKHdpZHRoID0gMSwgc3RhdCA9ICJpZGVudGl0eSIscG9zaXRpb24gPSAiZmlsbCIpKw0KICBmYWNldF93cmFwKH4gYnJva2UpKw0KICBjb29yZF9wb2xhcigieSIsIHN0YXJ0PTApKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiI0NDNjYwMCIsIiM2NjAwMDAiLCIjRkZDQzY2IikpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGFuZWwuZ3JpZCAgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvciA9ICJncmF5MTAiKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMCkpKw0KICBnZ3RpdGxlKCI5LkRlYnQgU3RydWdnbGVzIG1ha2VzIGZvb2QgYXQgaG9tZSIpDQpgYGANCg0KUGllIGNoYXJ0cyBpbiBjaGFydDkgc2hvdyB0aGUgcHJvcG9ydGlvbiBvZiBkaWZmZXJlbnQga2luZHMgb2YgZm9vZCBleHBlbnNlIGluIGRpZmZlcmVudCBicm9rZSBzdGF0dXMuIE5vIG1hdHRlciBiYW5rcnVwdGN5IG9yIGZvcmVjbG9zZSwgcGVvcGxlIHdpdGhvdXQgdGhlc2UgcHJvYmxlbXMgc3BlbmQgbW9yZSBvbiBmb29kIGF3YXkgZnJvbSBob21lLg0KDQoqKmNoYXJ0MTAqKg0KYGBge3J9DQojY2FsY3VsYXRlIHRoZSBjdW1zdW0gZm9yIHRoZSBnZW9tX3RleHQNCnNjZl9mb29kX2N1bSA8LSBwbHlyOjpkZHBseShzY2ZfZm9vZCwgImJyb2tlIiwNCiAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0sIHlwb3M9Y3Vtc3VtKHZhbHVlKSkNCg0KZ2dwbG90KHNjZl9mb29kX2N1bSxhZXMoeCA9IGJyb2tlKSkrDQogIGdlb21fYmFyKGFlcyh5ID0gdmFsdWUsIGdyb3VwID0gb3JkZXIsIGZpbGwgPSBrZXkpLA0KICAgICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjUpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQodmFsdWUpLCB5ID0geXBvcywgZ3JvdXAgPSBvcmRlciksDQogICAgICAgICAgICBzaXplID0gMywgY29sb3IgPSAiZ3JleTEwIiwgdmp1c3QgPSAtMSkrDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkV4cGVuc2VzIG9uIEZvb2QiLA0KICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLDkwMDApLA0KICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsOTAwMCwgYnkgPSAyMDAwKSkrDQogIHhsYWIoIkJyb2tlIFN0YXR1cyIpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiI0NDNjYwMCIsIiM2NjAwMDAiLCIjRkZDQzY2IikpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvciA9ICJncmF5MTAiKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMCkpKw0KICBnZ3RpdGxlKCIxMC5EZWJ0IFN0cnVnZ2xlcyBtYWtlcyBmb29kIGF0IGhvbWUiKQ0KYGBgDQoNClRoZSBzdGFja2VkIGJhciBjaGFydCBpbmRpY2F0ZXMgdGhlIGFtb3VudCBvZiB0aGUgZXhwZW5zZXMgb24gZm9vZCB0b2dldGhlciB3aXRoIHRoZSBwcm9wb3J0aW9uLiBGb3IgdGhlIGJhbmtydXB0Y3ksIHBlb3BsZSB3aXRoIHRoZSBwcm9ibGVtIHNwZW5kIGxlc3Mgb24gZGVsaXZlcnkgYW5kIGF3YXkgYW5kIGFsc28gaW4gdG90YWwgb24gYXZlcmFnZS4gQXMgZm9yIHBlb3BsZSBzdHJ1Z2dsaW5nIHdpdGggZm9yZWNsb3NlLCB0aG91Z2ggdGhleSBoYXZlIGEgaGlnaGVyIHByb3BvcnRpb24gb2YgaG9tZSBmb29kIGV4cGVuc2UsIHRoZXkgc3RpbGwgc3BlbmQgbW9yZSB0aGFuIDIsMDAwIGRvbGxhcnMgaW4gdG90YWwgdGhhbiB0aG9zZSB3aXRob3V0IGZvcmVjbG9zZSBpc3N1ZS4gV2UgY2FuIHRlbGwgZnJvbSBjaGFydDEwIHRoYXQgdGhlcmUgaXMgYSBub24tdGhyaWZ0eSBiZWhhdmlvciBpbiBmb3JlY2xvc2UuDQoNCkNoYXJ0MTAgaGFzIGEgYmV0dGVyIHBlcmZvcm1hbmNlIHRoYW4gY2hhcnQ5IGJlY2F1c2UgaXQgcHJvdmlkZXMgc29tZSBleHRyYSBpbmZvcm1hdGlvbiBvZiB0aGUgYW1vdW50IG9mIHRoZSBzcGVuZGluZyBhcyB3ZWxsIGFzIHRoZSBwcm9wb3J0aW9uLiBJdCBjYW4gc2hvdyB0aGUgYWN0dWFsIG5vbi10aHJpZnR5IGJlaGF2aW9yIG9mIHJlc3BvbmRlbnRzIGNvbXBhcmVkIHdpdGggY2hhcnQ5LiBUaGVyZWZvcmUsIEkgcmVjb21tYW5kIHVzZSBzdGFja2VkIGJhciBjaGFydCBoZXJlLg0KDQojIyA1LkludGVyYWN0aW9uDQoNClRoZSBzY2F0dGVyIHBsb3QgaXMgdXN1YWxseSBub3QgZWFzeSB0byB0ZWxsIGFwYXJ0IGZyb20gZWFjaCBwb2ludC4gVGhlcmVmb3JlLCBhZGRpbmcgYW4gaW50ZXJhY3Rpb24gdG8gdGhlIHNjYXR0ZXIgcGxvdCBpcyBuZWNlc3NhcnkuIEkgbWFkZSBhbiBpbnRlcmFjdGlvbiB0byBjaGFydDYgc28gdGhhdCByZWFkZXJzIGNhbiBzZWUgdGhlIHN0dWRlbnQgbG9hbiwgYWdlIGFuZCBkZWdyZWUgb2YgZWFjaCBwb2ludC4NCg0KYGBge3J9DQpnZ3Bsb3RseShhZ2VfZWR1KSU+JQ0KICBsYXlvdXQobGVnZW5kID0gbGlzdCh4ID0gMC41LCB5ID0gMSkpDQpgYGANCg0KSW4gb3JpZ2luYWwgY2hhcnQyLCB3ZSBjYW4gb25seSBzZWUgdGhlIHByb3BvcnRpb24gYnV0IG5vdCB0aGUgYWN0dWFsIGF2ZXJhZ2UgYW1vdW50IG9mIGRpZmZlcmVudCBsb2Fucywgc28gdGhhdCdzIHdoeSBJIGFkZCBhbiBpbnRlcmFjdGlvbiB0byB0aHVzIGNoYXJ0LiANCg0KYGBge3J9DQpnZ3Bsb3RseShsb2FuLCB0b29sdGlwID0gYygibG9hbiIsImFtb3VudCIpKQ0KYGBgDQoNCg0KIyMgNi4gRGF0YSBUYWJsZQ0KDQpUaGUgdGFibGUgc2hvd3MgYm90aCB0aGUgYW1vdW50IGFuZCBwcm9wb3J0aW9uIG9mIGxvYW4gZnJvbSBkaWZmZXJlbnQgY2F0ZWdvcnkgaW4gc3VydmV5IHllYXIgZnJvbSB0aGUgZGF0YXRhYmxlLiBSZWFkZXJzIGNhbiBzZWxlY3QgdGhlIHllYXIgYW5kIGxvYW4gb3IgZXZlbiBmaWx0ZXIgaXQgYnkgc2V0dGluZyB0aGUgcmFuZ2Ugb2YgYW1vdW50IGFuZCBwcm9wb3J0aW9uLg0KDQpgYGB7cn0NCnByZXR0eV9oZWFkZXJzIDwtIA0KICBnc3ViKCJbLl0iLCAiICIsIGNvbG5hbWVzKHNjZl9sb2FuKSkgJT4lDQogIHN0cl90b190aXRsZSgpDQoNCnNjZl9sb2FuICU+JQ0KICBkYXRhdGFibGUoDQogICAgcm93bmFtZXMgPSBGQUxTRSwNCiAgICBjb2xuYW1lcyA9IHByZXR0eV9oZWFkZXJzLA0KICAgIGZpbHRlciA9IGxpc3QocG9zaXRpb24gPSAidG9wIiksDQogICAgb3B0aW9ucyA9IGxpc3QobGFuZ3VhZ2UgPSBsaXN0KHNTZWFyY2ggPSAiRmlsdGVyOiIpKQ0KICApDQpgYGANCg0K